# encoding: utf-8
import settings

import logging, os, BaseHTTPServer, SocketServer
from jsonrpc import ServiceHandler
from api import API
from subprocess import Popen, PIPE
import openssl

from twisted.web import server, resource
from twisted.internet import reactor

logger = logging.getLogger('Global')

if settings.DEBUG:
    logger.setLevel(logging.DEBUG)
    consoleLog = logging.StreamHandler()
    consoleLog.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    consoleLog.setFormatter(formatter)
    logger.addHandler(consoleLog)

class Error(Exception):
    def __init__(self, name=None, code=None, message=None, httpCode=200):
        self.code = code
        self.httpCode = httpCode
        self.message = message
        self.name = name

class ThreadingHTTPServer( SocketServer.ThreadingMixIn, SocketServer.TCPServer, BaseHTTPServer.HTTPServer):
    pass

class ApiRequestHandler(resource.Resource):
    isLeaf = True

    def __init__(self, *argc, **named):
        global logger
        self.json_handler = ServiceHandler(API(max_execution_time=settings.MAX_EXECUTION_TIME, logger=logger))
        resource.Resource.__init__(self, *argc, **named)
    
    def render_GET(self, request):
        global logger
        logger.debug('GET request from ' + request.getClientIP())
        return "OK"
        
    def render_POST(self, request):
        global logger
        logger.debug('POST request from ' + request.getClientIP())
        try:
            data = request.content.read()
            if len(data) > settings.MAX_REQUEST_SIZE:
                logger.info('Max request size limit. Request site: ' + str(len(data)) + ' bytes.')
                raise Exception('Max request size limit %s bytes' % settings.MAX_REQUEST_SIZE)
            return self.handle_secure(data)
        except Exception, e:
            logger.warn('Exception', exc_info=e)
            if settings.DEBUG:
                request.setResponseCode(500, e.message)
            else:
                request.setResponseCode(500, 'Internal error')
            return ''

    def handle_secure(self, data):
        global logger
        logger.debug('Request secure mode: ' + str(settings.SECURE_MODE))
        if settings.SECURE_MODE == None:
            logger.debug('Request: ' + data)
            response = self.json_handler.handleRequest(data)
            logger.debug('Response: ' + response)
        elif settings.SECURE_MODE == 'OpenSSL':
            OPENSSL=settings.OPENSSL
            ssl = openssl.OpenSSL(OPENSSL['OpenSSL'], OPENSSL['PublicKey'], OPENSSL['SecretKey'], OPENSSL['TrustedKeys'])
            data, keyname = ssl.decrypt(data)
            logger.debug('Key name: ' + keyname)
            logger.debug('Request: ' + data)
            response = self.json_handler.handleRequest(data)
            logger.debug('Response: ' + response)
            response = ssl.encrypt(response, keyname)
        else:
            e = Exception()
            e.message = 'Unknown secure mode'
            raise e
        
        return response 
            
        
    def log_request(self, code='-', size='-'):
        pass

def test_settings():
    global logger
    if settings.SECURE_MODE == 'OpenSSL':
        from settings import OPENSSL
        if not os.path.isfile(OPENSSL['PublicKey']):
            logger.error("Can't find public key")
            return False
        if not os.path.isfile(OPENSSL['SecretKey']):
            logger.error("Can't find secrec key")
            return False
        if not os.path.isdir(OPENSSL['TrustedKeys']):
            logger.error("Can't find trusted key dirs")
            return False
        if not os.path.isfile(OPENSSL['OpenSSL']):
            logger.error("Can't find openssl")
            return False
    
    return True

def run():
    global logger
    if not test_settings():
        logger.error('Settings error. Exit from commander.')
        return False
    
    site = server.Site(ApiRequestHandler())
    if settings.IP_ADDR == '0.0.0.0': host = ''
    else: host = settings.IP_ADDR
    reactor.listenTCP(settings.IP_PORT, site, interface=host)
    logger.info('Start remote commader, %s:%s' % (settings.IP_ADDR, settings.IP_PORT))
    reactor.run()

if __name__ == '__main__':
    run()